package sysApi

import (
	"gitee.com/jokces/kit/errc"
	"gitee.com/jokces/kit/ginutil"
	sysModel "gitee.com/jokces/kit/global/admin/model"
	"github.com/gin-gonic/gin"
)

// 登陆 + 刷新token
// 接口: /:appType/oauth/token get/post
func (r *AdminRouter) accessToken(ctx *gin.Context) {
	if ok := sysModel.ValidateType(ctx.Param("appType")); !ok {
		ginutil.RespErr(ctx, errc.ErrAuthExpired.MultiMsg("只支持：admin or api"))
		return
	}
	method := ctx.Request.Method
	switch method {
	case "GET":
		token, err := r.s.RefreshToken(ctx)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, token)
		break
	case "POST":
		r.postAccessToken(ctx)
		break
	default:
		ginutil.RespErr(ctx, errc.ErrAuthExpired.MultiMsg("只支持：POST or GET"))
		return
	}
}

// 换取对应的accessToken
func (r *AdminRouter) postAccessToken(ctx *gin.Context) {
	in := &sysModel.AccessTokenReq{
		AppType: ctx.Param("appType"),
	}
	err := ginutil.ShouldBind(ctx, in)
	if err != nil {
		ginutil.RespErr(ctx, err)
		return
	}
	var (
		cli    *sysModel.SysOauthClient
		errors error
	)

	//默认的处理一个，就是总的服务
	cli, errors = r.s.ClientById(ctx, in.ClientId)
	if errors != nil || cli == nil {
		ginutil.RespErr(ctx, errc.ErrAccessDenied.MultiMsg("非法客户端请求"))
		return
	}

	switch in.GrantType {
	case sysModel.AuthorizationCode.ToString():
		//三方授权登录 client_id, response_type, scope, redirect_uri 来获取对应的code
		//1. 需要重定向到授权服务的登录页面
		//2. 用户在登录页面，进行账号密码登录，登录成功后；并记录对应的CODE -> redis中的缓存，然后进行重定向redirect_uri?code=1111,并携带对应的Code
		//3. 三方的界面获取到对应的code,然后组装参数提交到三方服务端
		//4. 三方服务端根据对应的code,也秘钥进行签名，提交到认证服务器。
		//5. 认证服务器返回对应的accessToken
		//7. authorization_code: 换取对应的code
		//8. 这里需要重定向相关的页面来处理

		//目前采用的方式是： 没有服务端的账户密码处理。直接简化的处理
		//不处理回调的处理
		if cli.DoesRootClient() {
			ginutil.RespErr(ctx, errc.ErrParamInvalid.MultiMsg("非法客户端请求"))
			return
		}
		if err := in.AuthCodeParam(); err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		code, err := r.s.AuthorizationCode(ctx, in, cli)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, code)
		break
	case sysModel.Password.ToString():
		if !cli.DoesRootClient() {
			ginutil.RespErr(ctx, errc.ErrParamInvalid.MultiMsg("三方登录不支持该模式"))
			return
		}
		login, err := r.s.UserPassLogin(ctx, in, cli)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, login)
		break
	case sysModel.Mobile.ToString():
		if !cli.DoesRootClient() {
			ginutil.RespErr(ctx, errc.ErrParamInvalid.MultiMsg("三方登录不支持该模式"))
			return
		}
		login, err := r.s.UserMobileLogin(ctx, in, cli)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, login)
		break
	case sysModel.Email.ToString():
		if !cli.DoesRootClient() {
			ginutil.RespErr(ctx, errc.ErrParamInvalid.MultiMsg("三方登录不支持该模式"))
			return
		}
		login, err := r.s.UserEmailLogin(ctx, in, cli)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, login)
		break
	case sysModel.RefreshToken.ToString():
		token, err := r.s.RefreshToken(ctx)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, token)
		break
	case sysModel.ClientCredentials.ToString():
		login, err := r.s.AuthorizationCodeLogin(ctx, in, cli)
		if err != nil {
			ginutil.RespErr(ctx, err)
			return
		}
		ginutil.RespData(ctx, login)
		break
	case sysModel.Wechat.ToString():
		//小程序，等其他的登录方式
		ginutil.RespErr(ctx, errc.ErrNotFound.MultiMsg("auth授权服务目前未开放"))
		break
	default:
		break
	}
}

// 退出登录
// 接口: /:appType/oauth/out post
func (r *AdminRouter) loginOut(ctx *gin.Context) {
	if ok := sysModel.ValidateType(ctx.Param("appType")); !ok {
		ginutil.RespErr(ctx, errc.ErrAuthExpired.MultiMsg("只支持：admin or api"))
		return
	}

	if err := r.s.LoginOut(ctx.GetHeader(sysModel.TokenHeader)); err != nil {
		ginutil.RespErr(ctx, errc.ErrInternalErr.MultiMsg("退出登录失败"))
		return
	}
	ginutil.RespSuccess(ctx)
}

// 检查token
// 接口: /:appType/oauth/check get
func (r *AdminRouter) checkToken(ctx *gin.Context) {
	if ok := sysModel.ValidateType(ctx.Param("appType")); !ok {
		ginutil.RespErr(ctx, errc.ErrAuthExpired.MultiMsg("只支持：admin or api"))
		return
	}
	in := &sysModel.CheckTokenReq{}
	err := ginutil.ShouldBind(ctx, in)
	if err != nil {
		ginutil.RespErr(ctx, err)
		return
	}
	if rs, err := r.s.CheckToken(in.Token); err != nil {
		ginutil.RespErr(ctx, err)
		return
	} else {
		ginutil.RespData(ctx, rs)
	}
}
